package com.mune.gulimall.seckill.config.mq;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@Configuration
public class RabbitConfig {

  @Resource
  RabbitTemplate rabbitTemplate;

  /**
   * 消息 json转换器
   *
   * @return
   */
  @Bean
  public MessageConverter messageConverter() {
    return new Jackson2JsonMessageConverter();
  }

  /**
   * 定制RabbitTemplate
   * 1、服务收到消息就会回调
   * 1、spring.rabbitmq.publisher-confirms: true
   * 2、设置确认回调
   * 2、消息正确抵达队列就会进行回调
   * 1、spring.rabbitmq.publisher-returns: true
   * spring.rabbitmq.template.mandatory: true
   * 2、设置确认回调ReturnCallback
   * <p>
   * 3、消费端确认(保证每个消息都被正确消费，此时才可以在队列删除这个消息)
   */
  @PostConstruct
  public void initRabbitTemplate() {

    /**
     * 返回通知
     * 1、只要消息抵达服务器交换机就ack=true
     * correlationData：当前消息的唯一关联数据(拥有唯一id)
     * ack：消息是否成功被交换机接收
     * cause：失败的原因
     */
    //设置确认回调
    rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
      System.out.println("confirm...correlationData[" + correlationData + "]==>ack:[" + ack + "]==>cause:[" + cause + "]");
    });


    /**
     *  异常通知
     * 只要消息没有路由到队列，就触发这个失败回调
     * message：投递失败的消息详细信息
     * replyCode：回复的状态码
     * replyText：回复的文本内容
     * exchange：当时这个消息发给哪个交换机
     * routingKey：当时这个消息用哪个路邮键
     */
    rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
      System.out.println("Fail Message[" + message + "]==>replyCode[" + replyCode + "]" +
              "==>replyText[" + replyText + "]==>exchange[" + exchange + "]==>routingKey[" + routingKey + "]");
    });
  }
}
